Conversation
Greptile SummaryThis PR fixes a bug in Key changes:
Confidence Score: 5/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["update_single(doc_id, user_fields)"] --> B{user_fields is None?}
B -- Yes --> C["project_ids = None\npersona_ids = None\n(no-op for both fields)"]
B -- No --> D{user_fields.user_projects\nis None?}
D -- "Yes (None)" --> E["project_ids = None\n(no-op)"]
D -- "No ([] or [1,2,...])" --> F["project_ids = set(user_projects)\n(e.g. set() clears the field)"]
E --> G{user_fields.personas\nis None?}
F --> G
G -- "Yes (None)" --> H["persona_ids = None\n(no-op)"]
G -- "No ([] or [1,2,...])" --> I["persona_ids = set(personas)\n(e.g. set() clears the field)"]
H --> J["MetadataUpdateRequest\n(None fields are skipped;\nempty sets clear the field)"]
I --> J
C --> J
J --> K["OpenSearch / Vespa\nupdate chunks"]
|
There was a problem hiding this comment.
1 issue found across 4 files
Confidence score: 4/5
- There’s a moderate risk of test failures: module-scoped fixtures in
backend/tests/external_dependency_unit/document_index/test_document_index_old.pydepend on function-scopedtenant_context, which can trigger pytestScopeMismatcherrors. - This is limited to the test suite and doesn’t imply a runtime regression, so the overall merge risk remains low.
- Pay close attention to
backend/tests/external_dependency_unit/document_index/test_document_index_old.py- fix fixture scoping to avoidScopeMismatcherrors.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="backend/tests/external_dependency_unit/document_index/test_document_index_old.py">
<violation number="1" location="backend/tests/external_dependency_unit/document_index/test_document_index_old.py:60">
P2: Module-scoped fixtures cannot depend on a function-scoped fixture. `tenant_context` should be module-scoped (or removed from those fixtures) to avoid pytest `ScopeMismatch` errors.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
backend/tests/external_dependency_unit/document_index/test_document_index_old.py
Outdated
Show resolved
Hide resolved
🖼️ Visual Regression Report
|
backend/tests/external_dependency_unit/document_index/test_document_index_old.py
Outdated
Show resolved
Hide resolved
backend/tests/external_dependency_unit/document_index/test_document_index_old.py
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
2 issues found across 6 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="backend/scripts/restart_containers.sh">
<violation number="1" location="backend/scripts/restart_containers.sh:32">
P2: The new `--keep-opensearch-data` flag is parsed but never removed from positional args, so passing the flag without volumes (or before them) turns it into the Vespa volume value and breaks the docker run command. Parse args into a filtered list or shift after handling the flag before assigning volumes.</violation>
</file>
<file name="backend/onyx/document_index/vespa/indexing_utils.py">
<violation number="1" location="backend/onyx/document_index/vespa/indexing_utils.py:282">
P1: Avoid logging raw `e.response.text` for non-retryable HTTP errors; it can expose sensitive response content in logs. Log only safe metadata such as status code and document id.
(Based on your team's feedback about avoiding raw exception/URL token leakage in logs.) [FEEDBACK_USED]</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
…ts-and-personas-empty
|
Preview Deployment
|
| @pytest.fixture(scope="function") | ||
| def index_batch_params() -> Generator[IndexBatchParams, None, None]: | ||
| yield IndexBatchParams( | ||
| doc_id_to_previous_chunk_cnt={"test_doc": 0}, | ||
| doc_id_to_new_chunk_cnt={"test_doc": 5}, | ||
| tenant_id=get_current_tenant_id(), | ||
| large_chunks_enabled=False, | ||
| ) |
There was a problem hiding this comment.
Hardcoded doc_id_to_previous_chunk_cnt will break future tests sharing module-scoped backends
doc_id_to_previous_chunk_cnt={"test_doc": 0} is hardcoded to 0, which is only correct on the very first index call. The document_indices fixture is scope="module", meaning the same OpenSearch and Vespa backends persist across all test functions in this module. When a second test function uses this fixture and calls document_index.index(...), the backend already has 5 chunks for "test_doc" from the previous test run, but the batch params still claim 0 prior chunks exist. This can lead to orphaned/duplicate chunks that make subsequent assertions incorrect.
The PR description explicitly states these fixtures should be reused for additional tests, so this will become a real problem quickly. Consider making the previous chunk count dynamic or resetting it to the correct value based on backend state, or using a per-test unique doc_id.
Prompt To Fix With AI
This is a comment left during a code review.
Path: backend/tests/external_dependency_unit/document_index/test_document_index_old.py
Line: 273-280
Comment:
**Hardcoded `doc_id_to_previous_chunk_cnt` will break future tests sharing module-scoped backends**
`doc_id_to_previous_chunk_cnt={"test_doc": 0}` is hardcoded to 0, which is only correct on the very first index call. The `document_indices` fixture is `scope="module"`, meaning the same OpenSearch and Vespa backends persist across all test functions in this module. When a second test function uses this fixture and calls `document_index.index(...)`, the backend already has 5 chunks for `"test_doc"` from the previous test run, but the batch params still claim `0` prior chunks exist. This can lead to orphaned/duplicate chunks that make subsequent assertions incorrect.
The PR description explicitly states these fixtures should be reused for additional tests, so this will become a real problem quickly. Consider making the previous chunk count dynamic or resetting it to the correct value based on backend state, or using a per-test unique `doc_id`.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
good feedback, ill add a comment in the code for future test authors about this but ive spent so long trying to get this test working that i dont care abt this in this pr.
There was a problem hiding this comment.
or i can just clean up the index between test cases. either way ill do this later.
| project_id=1, | ||
| persona_id=2, | ||
| ) | ||
| time.sleep(1) |
There was a problem hiding this comment.
Fixed-duration time.sleep makes tests fragile in slow CI environments
Using time.sleep(1) for Vespa and OpenSearch indexing propagation is a known source of test flakiness—on a loaded CI worker 1 second may not be enough for the write to be queryable. The vespa_document_index fixture already demonstrates a robust polling pattern (lines 145–154) that retries for up to 60 seconds. Applying a similar retry-until-consistent approach here would make these assertions more reliable:
import tenacity
@tenacity.retry(
stop=tenacity.stop_after_delay(10),
wait=tenacity.wait_fixed(0.5),
reraise=True,
)
def assert_chunk_count(document_index, chunk_request, filters, expected_count):
chunks = document_index.id_based_retrieval(chunk_requests=[chunk_request], filters=filters)
assert len(chunks) == expected_countThis pattern (or an equivalent simple polling loop) applies to the time.sleep(1) at line 342 as well.
Prompt To Fix With AI
This is a comment left during a code review.
Path: backend/tests/external_dependency_unit/document_index/test_document_index_old.py
Line: 316
Comment:
**Fixed-duration `time.sleep` makes tests fragile in slow CI environments**
Using `time.sleep(1)` for Vespa and OpenSearch indexing propagation is a known source of test flakiness—on a loaded CI worker 1 second may not be enough for the write to be queryable. The `vespa_document_index` fixture already demonstrates a robust polling pattern (lines 145–154) that retries for up to 60 seconds. Applying a similar retry-until-consistent approach here would make these assertions more reliable:
```python
import tenacity
@tenacity.retry(
stop=tenacity.stop_after_delay(10),
wait=tenacity.wait_fixed(0.5),
reraise=True,
)
def assert_chunk_count(document_index, chunk_request, filters, expected_count):
chunks = document_index.id_based_retrieval(chunk_requests=[chunk_request], filters=filters)
assert len(chunks) == expected_count
```
This pattern (or an equivalent simple polling loop) applies to the `time.sleep(1)` at line 342 as well.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
i know man im tired, just read the comment above in the code about this.
…ts-and-personas-empty
Description
Currently empty projects and personas are treated as None, meaning no update required, when really an empty list should mean clear these respective fields from the chunk.
This is a followup to #8680 (comment).
How Has This Been Tested?
I went through the effort of adding external dependency unit tests for this function of the old document index interface. Hopefully these fixtures can be used to easily add additional tests when needed. This took me more time and effort than I wanted, please clap.
Additional Options
Summary by cubic
Fixes updates so sending empty
user_projects/personasclears those fields in both OpenSearch and Vespa. Project/persona filters no longer match cleared chunks after clearing.update_singlefor both backends, treat empty lists as “clear”; send empty sets to clear fields and useNonewhen fields are omitted (no-op).Written for commit 1388cdd. Summary will update on new commits.